import {
	createContext,
	Component,
	useContext,
	Context,
	PureComponent,
	memo,
} from 'react'
import { defaultProps, defaultState } from '../types/baseType'

const MyContext = createContext<Theme>({})
const MyProvider = MyContext.Provider
const MyConsumer = MyContext.Consumer

interface Theme {
	color?: string
}

type State = defaultState & {
	theme: Theme
	count: number
}

function getRandomColor() {
	return '#' + Math.floor(Math.random() * Math.pow(10, 6))
}

export default class ContextPage extends Component<defaultProps, State> {
	constructor(props: defaultProps) {
		super(props)
		this.state = {
			theme: { color: 'red' },
			count: 0,
		}
	}

	handleClick = () => {
		this.setState((preState) => {
			return { count: preState.count + 1 }
		})
	}

	changeTheme = () => {
		this.setState({
			theme: {
				color: getRandomColor(),
			},
			count: 0,
		})
	}

	render() {
		const { theme, count } = this.state

		return (
			<div className="border">
				<h3>ContextPage</h3>
				<MyProvider value={theme}>
					<MyConsumer>{(ctx) => <Child {...ctx} />}</MyConsumer>
					<ClassChild />
					{/* 考点1：这里传递 context value 最好传入新的对象进去，否则每次父组件更新，子组件都会更新。比如传递 {...theme} */}
					<MyProvider value={theme}>
						<FunctionChild></FunctionChild>
					</MyProvider>
				</MyProvider>

				<button onClick={this.handleClick}>change count:{count}</button>
				<button onClick={this.changeTheme}>change theme color</button>
			</div>
		)
	}
}

class ClassChild extends PureComponent {
	static contextType: Context<Theme> = MyContext
	declare context: React.ContextType<typeof MyContext>

	render() {
		const { color } = this.context
		console.log('classChild - 重渲染')
		return (
			<div className="border">
				<button style={{ color: color }}>ClassChild-{color}</button>
			</div>
		)
	}
}

const FunctionChild = memo(() => {
	const context = useContext(MyContext)
	const { color } = context
	console.log('FunctionChild - 重渲染')
	return (
		<div className="border" style={{ color: color }}>
			FunctionChild: {color}
		</div>
	)
})

function Child({ color }: Theme) {
	return (
		<div className="border" style={{ color: color }}>
			Child-{color}
		</div>
	)
}
